home *** CD-ROM | disk | FTP | other *** search
/ Best Tools for JAVA / Best Tools for JAVA.iso / JAVA_ALL / IDE / SUBARTIC / SUB_ARCT / DEMO_APP / SPREAD_S.JAV < prev    next >
Encoding:
Text File  |  1996-10-04  |  12.8 KB  |  570 lines

  1. /*
  2.  * A simple spread_sheet using sub_arctic.  
  3.  * I took out all of the business with URLs & threads because I couldn't
  4.  * figure out what that was trying to do.  All of the parsing and calculating
  5.  * code is identical to the original.
  6.  * 9/24/96 Colleen Kehoe
  7.  *
  8.  * Based on: 
  9.  * @(#)SpreadSheet.java    1.17 95/03/09 Sami Shaio
  10.  * Copyright (c) 1994-1996 Sun Microsystems, Inc. All Rights Reserved.
  11.  *
  12.  */
  13.  
  14. package sub_arctic.demo_apps;
  15.  
  16. import java.awt.*;
  17. import java.io.*;
  18. import java.lang.*;
  19. import java.net.*;
  20.  
  21. import sub_arctic.lib.*;
  22. import sub_arctic.output.*;
  23. import sub_arctic.input.*;
  24. import sub_arctic.constraints.std_function;
  25.  
  26. public class spread_sheet extends interactor_applet {
  27.     String        title;
  28.     Font        titleFont;
  29.     int            cellWidth = 100;
  30.     Font        inputFont;
  31.     int            rows;
  32.     int            columns;
  33.     SpreadSheetInput    inputArea;
  34.     Cell        cells[][];
  35.     Cell        current = null;
  36.     grid                ss_grid;
  37.     boolean        isStopped = false; 
  38.     label               titleLabel;
  39.  
  40.   public void build_ui(base_parent_interactor top) {
  41.     String rs;
  42.     
  43.     inputFont = new Font("Courier", Font.PLAIN, 10);
  44.     titleFont = new Font("Courier", Font.BOLD, 12);
  45.     title = getParameter("title");
  46.     if (title == null) {
  47.         title = "Spreadsheet";
  48.     }
  49.     rs = getParameter("rows");
  50.     if (rs == null) {
  51.         rows = 9;
  52.     } else {
  53.         rows = Integer.parseInt(rs);
  54.     }
  55.     rs = getParameter("columns");
  56.     if (rs == null) {
  57.         columns = 5;
  58.     } else {
  59.         columns = Integer.parseInt(rs);
  60.     }
  61.  
  62.     // set up title
  63.     titleLabel = new label(title,titleFont);
  64.     titleLabel.set_x_constraint(std_function.eq(PARENT.X1()));
  65.     titleLabel.set_y_constraint(std_function.eq(PARENT.Y1()));
  66.     top.add_child(titleLabel);
  67.  
  68.     // inputArea is the bar you type into at the top
  69.     inputArea = new SpreadSheetInput(null,this);
  70.     inputArea.set_w_constraint(std_function.eq(PARENT.X2()));
  71.     inputArea.set_y_constraint(std_function.eq(PREV_SIBLING.Y2()));
  72.     top.add_child(inputArea);
  73.  
  74.     // set up labels--use the 0th row & column to store them
  75.     ss_grid = new grid(rows+1,columns+1);
  76.     char l[] = new char[1];
  77.     ss_grid.set_element_at(0,0,new label(""));
  78.     for (int i=1; i<=rows; i++) {
  79.       ss_grid.set_element_at(i,0,new label(String.valueOf(i)));
  80.     }
  81.     for (int j=1; j<=columns; j++) {
  82.       l[0] = (char)((int)'A' + j-1);
  83.       String s = new String(l);
  84.       // cheezy, I know
  85.       ss_grid.set_element_at(0,j,
  86.                  new label("       "+s,cellWidth-2));
  87.     }
  88.  
  89.     // create all cells first    
  90.     for (int i=1; i <= rows; i++) {
  91.       for (int j=1; j <= columns; j++) {
  92.         ss_grid.set_element_at(i,j, new Cell(this, 
  93.                          Color.yellow, 
  94.                          Color.black, 
  95.                          cellWidth - 2));
  96.       }
  97.     }
  98.  
  99.     // initialize cells with applet parameters
  100.     for (int i=1; i <= rows; i++) {
  101.         for (int j=1; j <= columns; j++) {
  102.           l[0] = (char)((int)'a' + j-1);
  103.           rs = getParameter("" + new String(l) + i);
  104.           if (rs != null) {
  105.         ((Cell)ss_grid.element_at(i,j)).setUnparsedValue(rs);
  106.           }
  107.         }
  108.     }
  109.     
  110.     ss_grid.set_y_constraint(std_function.eq(PREV_SIBLING.Y2()));
  111.     top.add_child(ss_grid);
  112.     
  113.  
  114.     }
  115.  
  116.     public void setCurrentValue(float val) {
  117.       current.setValue(val);
  118.     }
  119.  
  120.     public void stop() {
  121.     isStopped = true;
  122.     }
  123.  
  124.     public void start() {
  125.     isStopped = false;
  126.     }
  127.  
  128.     public void destroy() {
  129.     }
  130.  
  131.  
  132.     public void setCurrentCell(Cell c) {
  133.       unsetCurrentCell();
  134.       current = c;
  135.       current.select();
  136.       // display the value of the current cell in the inputArea
  137.       inputArea.set_text(new String(c.getPrintString()));
  138.       // set the selection point so it is not beyond the end of the text
  139.       inputArea.set_selection(oneline_text_display.SELECT_END,
  140.                   oneline_text_display.SELECT_END);
  141.     }
  142.  
  143.     public void unsetCurrentCell() {
  144.       if (current != null) {
  145.     current.deselect();
  146.     current = null;
  147.       }
  148.     }
  149.  
  150.     public void setCurrentValue(int type, String val) {
  151.       current.setValue(type,val);
  152.     }
  153.  
  154.     public void recalculate() {
  155.     int    i,j;
  156.  
  157.     for (i=1; i <= rows; i++) {
  158.       for (j=1; j <= columns; j++) {
  159.         if (((Cell)ss_grid.element_at(i,j)) != null && ((Cell)ss_grid.element_at(i,j)).type == Cell.FORMULA) {
  160.           ((Cell)ss_grid.element_at(i,j)).setRawValue(evaluateFormula(((Cell)ss_grid.element_at(i,j)).parseRoot));
  161.         }
  162.       }
  163.     }
  164.     }
  165.  
  166.     public float evaluateFormula(Node n) {
  167.     float    val = 0.0f;
  168.  
  169.     if (n == null) {
  170.         return val;
  171.     }
  172.     switch (n.type) {
  173.       case Node.OP:
  174.         val = evaluateFormula(n.left);
  175.         switch (n.op) {
  176.           case '+':
  177.         val += evaluateFormula(n.right);
  178.         break;
  179.           case '*':
  180.         val *= evaluateFormula(n.right);
  181.         break;
  182.           case '-':
  183.         val -= evaluateFormula(n.right);
  184.         break;
  185.           case '/':
  186.         val /= evaluateFormula(n.right);
  187.         break;
  188.         }
  189.         break;
  190.       case Node.VALUE:
  191.         return n.value;
  192.       case Node.CELL:
  193.         if (n == null) {
  194.         } else {
  195.           if (ss_grid.element_at(n.row+1,n.column+1) == null) {
  196.           } else {
  197.         return ((Cell)ss_grid.element_at(n.row+1,n.column+1)).value;
  198.           }
  199.         }
  200.     }
  201.  
  202.     return val;
  203.     }    
  204.  
  205.  
  206. }
  207.  
  208.  
  209. class Cell extends oneline_text_display implements pressable {
  210.     public static final int VALUE = 0;
  211.     public static final int LABEL = 1;
  212.     public static final int URL   = 2;
  213.     public static final int FORMULA = 3;
  214.     
  215.     Node    parseRoot;
  216.     boolean selected = false;
  217.     boolean transientValue = false;
  218.     public int    type = Cell.VALUE;
  219.     String    valueString = "";
  220.     String    printString = "v";
  221.     float    value;
  222.     spread_sheet app;
  223.     // the color to use when this cell is selected
  224.     color_pair selected_cp;
  225.  
  226.  
  227.     public Cell(spread_sheet app,
  228.         Color bgColor,
  229.         Color fgColor,
  230.         int width) {
  231.         super(0,0,width,null,null,false);
  232.     this.app = app;
  233.     selected_cp = new color_pair(fgColor,bgColor);
  234.     }
  235.         
  236.     public void setRawValue(float f) {
  237.     valueString = Float.toString(f);
  238.     value = f;
  239.     set_text(valueString);
  240.     }
  241.     public void setValue(float f) {
  242.     setRawValue(f);
  243.     set_text(valueString);
  244.     printString = "v" + valueString;
  245.     type = Cell.VALUE;
  246.     app.recalculate();
  247.     }
  248.  
  249.     public void setTransientValue(float f) {
  250.     transientValue = true;
  251.     value = f;
  252.     app.recalculate();
  253.     }
  254.  
  255.     public void setUnparsedValue(String s) {
  256.     switch (s.charAt(0)) {
  257.       case 'v':
  258.         setValue(Cell.VALUE, s.substring(1));
  259.         break;
  260.       case 'f':
  261.         setValue(Cell.FORMULA, s.substring(1));
  262.         break;
  263.       case 'l':
  264.         setValue(Cell.LABEL, s.substring(1));
  265.         break;
  266.     }
  267.     }
  268.  
  269.     /**
  270.      * Parse a spreadsheet formula. The syntax is defined as:
  271.      *
  272.      * formula -> value
  273.      * formula -> value op value
  274.      * value -> '(' formula ')'
  275.      * value -> cell
  276.      * value -> <number>
  277.      * op -> '+' | '*' | '/' | '-'
  278.      * cell -> <letter><number>
  279.      */
  280.     public String parseFormula(String formula, Node node) {
  281.     String subformula;
  282.     String restFormula;
  283.     float value;
  284.     int length = formula.length();
  285.     Node left;
  286.     Node right;
  287.     char op;
  288.  
  289.     if (formula == null) {
  290.         return null;
  291.     }
  292.     subformula = parseValue(formula, node);
  293.     if (subformula == null || subformula.length() == 0) {
  294.         return null;
  295.     }
  296.     if (subformula == formula) {
  297.         return formula;
  298.     }
  299.  
  300.     // parse an operator and then another value
  301.     switch (op = subformula.charAt(0)) {
  302.       case 0:
  303.         return null;
  304.       case ')':
  305.         return subformula;
  306.       case '+':
  307.       case '*':
  308.       case '-':
  309.       case '/':
  310.         restFormula = subformula.substring(1);
  311.         subformula = parseValue(restFormula, right=new Node());
  312.         if (subformula != restFormula) {
  313.         left = new Node(node);
  314.         node.left = left;
  315.         node.right = right;
  316.         node.op = op;
  317.         node.type = Node.OP;
  318.         return subformula;
  319.         } else {
  320.         return formula;
  321.         }
  322.       default:
  323.         return formula;
  324.     }
  325.     }
  326.  
  327.     public String parseValue(String formula, Node node) {
  328.     char    c = formula.charAt(0);
  329.     String    subformula;
  330.     String    restFormula;
  331.     float    value;
  332.     int    row;
  333.     int    column;
  334.  
  335.     restFormula = formula;
  336.     if (c == '(') {
  337.         restFormula = formula.substring(1);
  338.         subformula = parseFormula(restFormula, node);
  339.         if (subformula == null ||
  340.         subformula.length() == restFormula.length()) {
  341.         return formula;
  342.         } else if (! (subformula.charAt(0) == ')')) {
  343.         return formula;
  344.         }
  345.         restFormula = subformula;
  346.     } else if (c >= '0' && c <= '9') {
  347.         int i;
  348.  
  349.         try {
  350.         value = Float.valueOf(formula).floatValue();
  351.         } catch (NumberFormatException e) {
  352.         return formula;
  353.         }
  354.         for (i=0; i < formula.length(); i++) {
  355.         c = formula.charAt(i);
  356.         if ((c < '0' || c > '9') && c != '.') {
  357.             break;
  358.         }
  359.         }
  360.         node.type = Node.VALUE;
  361.         node.value = value;
  362.         restFormula = formula.substring(i);
  363.         return restFormula;
  364.     } else if (c >= 'A' && c <= 'Z') {
  365.         int i;
  366.  
  367.         column = c - 'A';
  368.         restFormula = formula.substring(1);
  369.         row = Float.valueOf(restFormula).intValue();
  370.         for (i=0; i < restFormula.length(); i++) {
  371.         c = restFormula.charAt(i);
  372.         if (c < '0' || c > '9') {
  373.             break;
  374.         }
  375.         }
  376.         node.row = row - 1;
  377.         node.column = column;
  378.         node.type = Node.CELL;
  379.         if (i == restFormula.length()) {
  380.         restFormula = null;
  381.         } else {
  382.         restFormula = restFormula.substring(i);
  383.         if (restFormula.charAt(0) == 0) {
  384.             return null;
  385.         }
  386.         }        
  387.     }
  388.  
  389.     return restFormula;
  390.     }
  391.  
  392.  
  393.     public void setValue(int type, String s) {
  394.     valueString = new String(s);
  395.     this.type = type;
  396.     switch (type) {
  397.       case Cell.VALUE:
  398.         setValue(Float.valueOf(s).floatValue());
  399.         break;
  400.       case Cell.LABEL:
  401.         set_text(valueString);
  402.         printString = "l" + valueString;
  403.         break;
  404.       case Cell.FORMULA:
  405.         parseFormula(valueString, parseRoot = new Node());
  406.         printString = "f" + valueString;
  407.         set_text(valueString);
  408.         break;
  409.     }
  410.     app.recalculate();
  411.     }
  412.  
  413.     public String getValueString() {
  414.     return valueString;
  415.     }
  416.  
  417.     public String getPrintString() {
  418.       return printString;
  419.     }
  420.  
  421.     public void select() {
  422.     selected = true;
  423.     set_colors(selected_cp);
  424.     }
  425.     public void deselect() {
  426.     selected = false;
  427.     set_colors(null);
  428.     }
  429.  
  430.   public boolean press(event evt,
  431.                Object user_info) {
  432.     return true;
  433.   }
  434.  
  435.   public boolean release(event evt,
  436.              Object user_info) {
  437.     // selection only takes effect on release, so that the
  438.     // user can back out if they want to
  439.       app.setCurrentCell(this);
  440.       return true;
  441.   }
  442.  
  443.  
  444.  
  445. }
  446.  
  447. class Node {
  448.     public static final int OP = 0;
  449.     public static final    int VALUE = 1;
  450.     public static final int CELL = 2;
  451.  
  452.     int        type;
  453.     Node     left;
  454.     Node     right;
  455.     int      row;
  456.     int      column;
  457.     float    value;
  458.     char    op;
  459.  
  460.     public Node() {
  461.     left = null;
  462.     right = null;
  463.     value = 0;
  464.     row = -1;
  465.     column = -1;
  466.     op = 0;
  467.     type = Node.VALUE;
  468.     }
  469.     public Node(Node n) {
  470.     left = n.left;
  471.     right = n.right;
  472.     value = n.value;
  473.     row = n.row;
  474.     column = n.column;
  475.     op = n.op;
  476.     type = n.type;
  477.     }
  478.     public void indent(int ind) {
  479.     for (int i = 0; i < ind; i++) {
  480.         System.out.print(" ");
  481.     }
  482.     }
  483.     public void print(int indentLevel) {
  484.     char l[] = new char[1];
  485.     indent(indentLevel);
  486.     System.out.println("NODE type=" + type);
  487.     indent(indentLevel);
  488.     switch (type) {
  489.       case Node.VALUE:
  490.         System.out.println(" value=" + value);
  491.         break;
  492.       case Node.CELL:
  493.         l[0] = (char)((int)'A' + column);
  494.         System.out.println(" cell=" + new String(l) + (row+1));
  495.         break;
  496.       case Node.OP:
  497.         System.out.println(" op=" + op);
  498.         left.print(indentLevel + 3);
  499.         right.print(indentLevel + 3);
  500.         break;
  501.     }
  502.     }
  503. }
  504.  
  505.  
  506. class SpreadSheetInput extends oneline_text_edit {
  507.  
  508.   spread_sheet app;
  509.  
  510.     public SpreadSheetInput(String initValue,
  511.                 spread_sheet app) {
  512.       super(initValue);
  513.       this.app = app;
  514.     }
  515.  
  516.  
  517.   // this means to consider the "eol" (i.e. return) character to be a
  518.   // special action character
  519.   public int char_filter(int input_char, int modifiers) {
  520.     return text_focus_agent.eol_action(input_char);
  521.   }
  522.  
  523.   // when we get the action character (i.e. return) we update the value of
  524.   // the current cell with what was typed in
  525.   public boolean action_char(event evt, char ch, Object user_info) {
  526.     float f;
  527.  
  528.     switch (text().charAt(0)) {
  529.       case 'v':
  530.         try {
  531.         f = Float.valueOf(text().substring(1)).floatValue();
  532.         ((spread_sheet)app).setCurrentValue(f);
  533.         } catch (NumberFormatException e) {
  534.         System.out.println("Not a float...");
  535.         }
  536.         break;
  537.       case 'l':
  538.         ((spread_sheet)app).setCurrentValue(Cell.LABEL, text().substring(1));
  539.         break;
  540.       case 'f':
  541.         ((spread_sheet)app).setCurrentValue(Cell.FORMULA, text().substring(1));
  542.         break;
  543.     }
  544.     return true;
  545.     }
  546. }
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554. /*=========================== COPYRIGHT NOTICE ===========================
  555.  
  556. This file is part of the subArctic user interface toolkit.
  557.  
  558. Copyright (c) 1996 Scott Hudson and Ian Smith
  559. All rights reserved.
  560.  
  561. The subArctic system is freely available for most uses under the terms
  562. and conditions described in 
  563.   http://www.cc.gatech.edu/gvu/ui/sub_arctic/sub_arctic/doc/usage.html 
  564. and appearing in full in the lib/interactor.java source file.
  565.  
  566. The current release and additional information about this software can be 
  567. found starting at: http://www.cc.gatech.edu/gvu/ui/sub_arctic/
  568.  
  569. ========================================================================*/
  570.